package io.gitee.kotle.player.ui.view.exo

import android.content.Context
import android.graphics.drawable.AnimationDrawable
import android.util.AttributeSet
import android.widget.Toast
import androidx.appcompat.widget.AppCompatImageView
import androidx.media3.common.MediaItem
import io.gitee.kotle.player.core.IPlayer
import io.gitee.kotle.player.core.impl.exoplayer.IExoPlayerMode
import io.gitee.kotle.player.download.IPlayerDownload
import io.gitee.kotle.player.ui.ignoreError
import io.gitee.kotle.player.ui.invisible
import io.gitee.kotle.player.ui.visible
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext

/**
 *
 * 描述：文件下载view
 *
 * @author Jiale.Wei
 *
 * 创建时间：2023/1/9 15:03
 *
 */
class ExoPlayerDownloadView : AppCompatImageView, IExoPlayerView {

    constructor(context: Context) : super(context)
    constructor(context: Context, attrs: AttributeSet?) : super(context, attrs)
    constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(
        context,
        attrs,
        defStyleAttr
    )

    init {
        invisible()
        setImageResource(android.R.drawable.stat_sys_download_done)
    }

    private var _player: IPlayer<MediaItem, IExoPlayerMode>? = null
    private var _config: ExoPlayerViewConfig<IExoPlayerMode>? = null

    private var listenerPair: Pair<String, IPlayerDownload.IListener<MediaItem>>? = null

    private var lastState: IPlayerDownload.State? = null
    private val listener = object : IPlayerDownload.IListener<MediaItem> {
        override suspend fun onDownload(downloadInfo: IPlayerDownload.DownloadInfo<MediaItem>) {
            val currentState = downloadInfo.state
            if (lastState != currentState) {
                lastState = currentState
                when (currentState) {
                    IPlayerDownload.State.Completed -> {
                        invisible()
                        Toast.makeText(context, "下载完成", Toast.LENGTH_SHORT).show()
                    }

                    IPlayerDownload.State.Downloading -> {
                        setImageResource(android.R.drawable.stat_sys_download)
                        val d = drawable
                        if (d is AnimationDrawable) {
                            d.start()
                        }
                    }

                    IPlayerDownload.State.Failed,
                    IPlayerDownload.State.Queued,
                    IPlayerDownload.State.Removing,
                    IPlayerDownload.State.Restarting,
                    IPlayerDownload.State.Removed,
                    IPlayerDownload.State.Stopped -> {
                        setImageResource(android.R.drawable.stat_sys_download_done)
                    }
                }
            }
        }
    }

    override fun onPlayerViewConfigCreated(
        player: IPlayer<MediaItem, IExoPlayerMode>,
        config: ExoPlayerViewConfig<IExoPlayerMode>
    ) {
        super.onPlayerViewConfigCreated(player, config)
        _player = player
        _config = config
        config.singleTapConfirmed.observeForever(::singleTapConfirmed)
        setOnClickListener {
            if (lastState == IPlayerDownload.State.Downloading) {
                //正在下载中
                return@setOnClickListener
            }
            val downloader = player.downloader ?: return@setOnClickListener
            val currentModel = ignoreError { player.currentModel } ?: return@setOnClickListener
            player.scope.launch {
                val mediaId = currentModel.getMediaId(this, player)
                val media = currentModel.getDownloadMedia(this, player, mediaId)
                if (media != null) {
                    addListener(downloader, mediaId)
                    downloader.addDownload(
                        mediaId,
                        media,
                        currentModel.getTitle(this, player)?.toByteArray()
                    )
                    Toast.makeText(
                        context,
                        "开始下载《${currentModel.getTitle(this, player)}》",
                        Toast.LENGTH_SHORT
                    ).show()
                } else {
                    Toast.makeText(
                        context,
                        "无法下载《${currentModel.getTitle(this, player)}》",
                        Toast.LENGTH_SHORT
                    ).show()
                }
            }
        }
    }

    override fun onPlayerViewConfigDestroyed(
        player: IPlayer<MediaItem, IExoPlayerMode>,
        config: ExoPlayerViewConfig<IExoPlayerMode>
    ) {
        super.onPlayerViewConfigDestroyed(player, config)
        _player = null
        _config = null
        player.downloader?.removeListener(listenerPair)
        config.singleTapConfirmed.removeObserver(::singleTapConfirmed)
    }


    private fun singleTapConfirmed(show: Boolean?) {
        show ?: return
        checkStatus()
    }

    override fun needPlayerListener(): Boolean {
        return true
    }

    override suspend fun onModelChange(
        scope: CoroutineScope,
        player: IPlayer<MediaItem, IExoPlayerMode>,
        oldModel: IExoPlayerMode?,
        newModel: IExoPlayerMode
    ) {
        super.onModelChange(scope, player, oldModel, newModel)
        lastState = null
        checkStatus()
    }

    private fun checkStatus() {
        if (_player?.hasModel != true) {
            return
        }
        val player = _player ?: return
        val currentModel = ignoreError { player.currentModel } ?: return
        val downloader = player.downloader
        //不支持下载
        if (downloader == null) {
            invisible()
            return
        }
        //页面隐藏
        if (_config?.singleTapConfirmed?.value == false) {
            invisible()
            return
        }
        //已经下载完成，不需要在显示
        if (lastState == IPlayerDownload.State.Completed) {
            invalidate()
            return
        }
        //有正在下载的资源
        if (lastState != null) {
            visible()
            return
        }
        player.scope.launch {
            val mediaId = currentModel.getMediaId(this, player)
            val download = withContext(Dispatchers.IO) { player.downloader?.getDownload(mediaId) }
            if (download == null) {
                visible()
            } else {
                if (download.state != IPlayerDownload.State.Completed) {
                    visible()
                    addListener(downloader, mediaId)
                    if (download.state != IPlayerDownload.State.Downloading) {
                        downloader.resumeDownload(mediaId)
                    }
                } else {
                    invisible()
                }
            }
        }
    }

    private fun addListener(downloader: IPlayerDownload<MediaItem>, mediaId: String) {
        downloader.removeListener(listenerPair)
        downloader.addListener(Pair(mediaId, listener).also {
            listenerPair = it
        })
    }
}